﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Data;
using System.Windows.Media;
using System.Windows.Data;
using System.Windows.Threading;
using System.Threading.Tasks;

namespace FindDuplicateFile
{

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class DuplicateFileFinder : Window, INotifyPropertyChanged
    {
        public DuplicateFileFinder()
        {
            this.DataContext = this;
            InitializeComponent();


            ChangeDirectory(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

            this.btnStartScan.IsEnabled = true;
            this.btnExportExcel.IsEnabled = false;

            wipDirectorySystem = new WorkInProgress(this, this.lblRepertoireProgress, this.pbRepertoireProgress);
            wipFilesSystem = new WorkInProgress(this, this.lblFichiersProgress, this.pbFichiersProgress);
            wipDuplicateFiles = new WorkInProgress(this, this.lblDuplicateFileProgress, this.pbDuplicateFileProgress);
            wipExplorer = new WorkInProgress(this, this.lblExplorerProgress, this.pbExplorerProgress);
        }

        private FSNode GetSelectedFSNode()
        {
            System.Windows.Controls.DataGrid dataGrid = null;

            if (this.TabCtrl.SelectedItem == this.tbiDuplicateFiles)
                dataGrid = this.gridDuplicateFiles;
            else
                dataGrid = null; // Pas normal

            return (FSNode)dataGrid.SelectedItem;
        }

        private void mnuOpenFolder(object sender, RoutedEventArgs e)
        {
            FSNode node = GetSelectedFSNode();
            if (node != null)
                node.OpenDirectory();
        }

        private void mnuOpenFile(object sender, RoutedEventArgs e)
        {
            FSNode node = GetSelectedFSNode();
            if (node != null)
                node.OpenFile();
        }

        private void mnuDeleteFile(object sender, RoutedEventArgs e)
        {
            FSNode node = GetSelectedFSNode();
            if (node != null)
                node.Delete();

            // $$$ TODO
            //if (FilePath != null  && File.Exists(FilePath))
            //{
            //    File.Delete(FilePath);

            //    List<FileAttrib> source = dataGrid1.ItemsSource as List<FileAttrib>;
            //    source.RemoveAt(dataGrid1.SelectedIndex);
            //    dataGrid1.ItemsSource = source;

            //    CollectionView cv = (CollectionView)CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
            //    PropertyGroupDescription pgd = new PropertyGroupDescription("fileImpression");
            //    cv.GroupDescriptions.Add(pgd);
            //}
        }

        private void btnChangeDir_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog folderDialog = new FolderBrowserDialog();
            folderDialog.Description = "Selectionner un dossier à explorer.";
            folderDialog.SelectedPath = this.currentPath;
            folderDialog.ShowNewFolderButton = false;

            DialogResult result = folderDialog.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                ChangeDirectory(folderDialog.SelectedPath);
            }
        }

        private void btnReScan_Click(object sender, RoutedEventArgs e)
        {
            ChangeDirectory(this.txtDir.Text);
        }

        private void btnStartScan_Click(object sender, RoutedEventArgs e)
        {
            if (FilesSystem != null && FilesSystem.Count > 5000)
            {
                string sMessage = string.Format("L'analyse de {0} fichier va être un peut longue.\nMais bon, Moi je peux le faire.\nEt vous, vous êtez pret à attendre un peut ?", FilesSystem.Count);
                MessageBoxResult res = System.Windows.MessageBox.Show(this, 
                    sMessage, 
                    "Vous êtez sur ?",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Exclamation,
                    MessageBoxResult.Yes);
                if (res != MessageBoxResult.Yes) return;
            }

            this.btnStartScan.IsEnabled = false;
            this.btnExportExcel.IsEnabled = false;
            gridDuplicateFiles.ItemsSource = null;

            // Calcul des data
            Task taskBuildDuplicateFile = new Task(() =>
            {

                DuplicateFiles = FSNodeBuilder.GetDuplicateFiles(FilesSystem, wipDuplicateFiles);

                this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() =>
                {
                    gridDuplicateFiles.ItemsSource = DuplicateFiles;

                    CollectionView cv = (CollectionView)CollectionViewSource.GetDefaultView(gridDuplicateFiles.ItemsSource);
                    PropertyGroupDescription pgd = new PropertyGroupDescription("MD5Hash");
                    cv.GroupDescriptions.Add(pgd);

                    this.btnStartScan.IsEnabled = true;
                    this.btnExportExcel.IsEnabled = true;
                }));
            });

            taskBuildDuplicateFile.Start();
        }

        private void btnExportExcel_Click(object sender, RoutedEventArgs e)
        {
            // $$$ TODO
            //if (this.dataGrid1.ItemsSource == null) return;

            //List<FileAttrib> outputRows = this.dataGrid1.ItemsSource as List<FileAttrib>;

            //object oOpt = System.Reflection.Missing.Value; //for optional arguments
            //Microsoft.Office.Interop.Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
            //Microsoft.Office.Interop.Excel.Workbooks oWBs = oXL.Workbooks;
            //Microsoft.Office.Interop.Excel._Workbook oWB = oWBs.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
            //Microsoft.Office.Interop.Excel._Worksheet oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.Sheets[1];

            //int numberOfRows = outputRows.Count;
            //Microsoft.Office.Interop.Excel.Range oRange;

            //oRange = oSheet.get_Range("A1", "A1");
            //oRange.Value2 = "Nom du fichier";
            //oRange = oSheet.get_Range("B1", "B1");
            //oRange.Value2 = "Chemin";
            //oRange = oSheet.get_Range("C1", "C1");
            //oRange.Value2 = "Taille";
            //oRange = oSheet.get_Range("D1", "D1");
            //oRange.Value2 = "Creation Time";
            //oRange = oSheet.get_Range("E1", "E1");
            //oRange.Value2 = "Last Access Time";
            //oRange = oSheet.get_Range("F1", "F1");
            //oRange.Value2 = "Last Write Time";
            //oRange = oSheet.get_Range("F1", "F1");
            //oRange.Value2 = "Groupe";

            //int row = 2;
            //foreach (FileAttrib fa in outputRows)
            //{
            //    oRange = oSheet.get_Range("A"+row.ToString(), "A"+row.ToString());
            //    oRange.Value2 = fa.Name;
            //    oRange = oSheet.get_Range("B"+row.ToString(), "B"+row.ToString());
            //    oRange.Value2 = fa.Path;
            //    oRange = oSheet.get_Range("C"+row.ToString(), "C"+row.ToString());
            //    oRange.Value2 = fa.Size;
            //    oRange = oSheet.get_Range("D"+row.ToString(), "D"+row.ToString());
            //    oRange.Value2 = fa.CreationTime.ToString();
            //    oRange = oSheet.get_Range("E"+row.ToString(), "E"+row.ToString());
            //    oRange.Value2 = fa.LastAccessTime.ToString();
            //    oRange = oSheet.get_Range("F"+row.ToString(), "F"+row.ToString());
            //    oRange.Value2 = fa.LastWriteTime.ToString();
            //    oRange = oSheet.get_Range("G" + row.ToString(), "G" + row.ToString());
            //    oRange.Value2 = fa.fileImpression;

            //    row++;
            //}

            //oXL.Visible = true;
            //oXL.UserControl = true;
        }

        private void ChangeDirectory(string sNewDir)
        {
            this.currentPath = sNewDir;
            this.txtDir.Text = sNewDir;

            gridRepertoires.Directories = null;
            gridFichiers.Files = null;
            ExplorerFS.CurrentDir = null;


            // Calcul des data
            Task taskBuildDirectory = new Task(() =>
            {
                this.DirectorySystem = FSNodeBuilder.GetDirectorySystem(FileSystemRoot, wipDirectorySystem);
                this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => gridRepertoires.Directories = DirectorySystem));
            });

            Task taskBuildFile = new Task(() =>
            {
                FilesSystem = FSNodeBuilder.GetFilesSystem(FileSystemRoot, wipFilesSystem);
                this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => gridFichiers.Files = FilesSystem));
            });

            Task taskBuildRoot = new Task(() =>
            {
                //DirectoryInfo dinfo = new DirectoryInfo(this.currentPath);
                //FileSystemRoot = FSDirectoryNode.CreateFSDirectoryNode(null, dinfo, "*." + this.searchExtension, wipExplorer);
                FileSystemRoot = FSNodeBuilder.GetExplorerSystem(this.currentPath, this.searchExtension, wipExplorer);
                this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => ExplorerFS.CurrentDir = this.FileSystemRoot));
            });
            taskBuildRoot.ContinueWith((dummy) =>
            {
                taskBuildFile.Start();
                taskBuildDirectory.Start();
            });

            taskBuildRoot.Start();
        }

        public string searchExtension = "*.*";
        public string currentPath = "D:\\TEMP";

        public FSDirectoryNode FileSystemRoot
        {
            get;
            set;
        }

        public List<FSDirectoryNode> DirectorySystem
        {
            get;
            set;
        }

        public List<FSFileNode> FilesSystem
        {
            get;
            set;
        }

        public List<FSFileNode> DuplicateFiles
        {
            get;
            set;
        }

        public WorkInProgress wipDirectorySystem { get; set; }
        public WorkInProgress wipFilesSystem { get; set; }
        public WorkInProgress wipDuplicateFiles { get; set; }
        public WorkInProgress wipExplorer { get; set; }

        #region Fucking/Garbage for : INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion Fucking/Garbage for : INotifyPropertyChanged
    }
}
